package com.cgycms.webloggather.file;

import com.cgycms.weblogcommon.model.gather.GatherConfig;
import com.cgycms.weblogcommon.model.gather.GatherInputs;
import com.cgycms.weblogcommon.model.gather.GatherMonitor;
import com.cgycms.webloggather.netty.NettyClient;
import com.cgycms.webloggather.util.GatherContext;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName : FileListenerFactory
 * @Description : 文件目录监听配置类
 * @Author : cgy
 * @Date: 2020-09-11 17:47
 */
@Component
public class FileListenerFactory {

    private static Logger log = LoggerFactory.getLogger(FileListenerFactory.class);

    private static List<FileAlterationMonitor> monitors = new ArrayList<>();


    @Autowired
    private GatherContext context;

    /**
     * 装配路径，并启动监控
     */
    @PostConstruct
    public void initMonitor() {
            log.info("Initializing FileListenerFactory...");
            GatherMonitor gatherMonitorConfig = context.findGatherMonitorConfig();
            long interval = TimeUnit.MILLISECONDS.toMillis(gatherMonitorConfig.getGatherConfig().getInterval());
            for (GatherInputs gatherInputs : gatherMonitorConfig.getInputs()) {
                String source = gatherInputs.getName();
                List<String> path = gatherInputs.getPath();
                path.forEach(s -> monitors.add(getMonitor(interval, source, s, gatherInputs.getFile())));
            }
            startMonitor();
    }

    /**
     * 构建监控对象
     * @param interval 间隔时间
     * @param source  来源
     * @param path    路径
     * @param fileName 文件
     * @return
     */
    private  FileAlterationMonitor getMonitor(long interval, String source, String path, String fileName) {
        log.info("Initializing FileAlterationMonitor path:({}),fileName:({})", path, fileName);
        IOFileFilter directories = FileFilterUtils.and(FileFilterUtils.directoryFileFilter());
        IOFileFilter suffixFileFilter = FileFilterUtils.suffixFileFilter(fileName == null ? "" : fileName);
        IOFileFilter files = FileFilterUtils.and(FileFilterUtils.fileFileFilter(), suffixFileFilter);
        IOFileFilter ioFileFilter = FileFilterUtils.or(directories, files);
        FileAlterationObserver observer = new FileAlterationObserver(path, ioFileFilter);
        GatherConfig config =  context.getConfig();
        observer.addListener(new FileListener(source,new NettyClient(config)));
        return new FileAlterationMonitor(interval, observer);
    }


    /**
     * 开启所有监控
     */
    public void startMonitor() {
        log.info("StartMonitor Success!");
        monitors.forEach(s -> {
            try {
                s.start();
            } catch (Exception e) {
                log.error("start monitor error!");
                e.printStackTrace();
            }
        });
    }

    /**
     * 关闭所有监控
     */
    public void stopMonitor() {
        log.info("stopMonitor Success!");
        monitors.parallelStream().forEach(s -> {
            try {
                s.stop();
            } catch (Exception e) {
                log.error("stop monitor error!");
                e.printStackTrace();
            }
        });
    }


}
